
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>

#define _CRT_SECURE_NO_WARNINGS

#define paddle_speed 2
#define ballspeed 0.3

struct data
{
	float x;
	float y;
	int message;
};


sf::Packet& operator <<(sf::Packet& Packet, const data& C)
{
    return Packet << C.x << C.y << C.message;
}

sf::Packet& operator >>(sf::Packet& Packet, data& C)
{
	return Packet >> C.x >> C.y >> C.message;
}

////////////////////////////////////////////////////////////
/// Create a client and connect it to a running server
///
////////////////////////////////////////////////////////////
void DoClientTCP(unsigned short Port)
{
	sf::RenderWindow app( sf::VideoMode( 800, 600 ),"Client", sf::Style::Resize );
	app.SetBackgroundColor( sf::Color(0,0,0) );


	sf::Image img;
	sf::Image ball;
	img.LoadFromFile( "left_paddle.png" );
	ball.LoadFromFile( "ball.bmp" );

	sf::Sprite spr[2];
	sf::Sprite sprball;

	spr[0].SetImage( img );
	spr[0].SetPosition( 10.f , 10.f );

	spr[1].SetImage( img );
	spr[1].SetPosition( 790.f - spr[1].GetWidth(), 10.f );
	spr[1].FlipX( true );

	sprball.SetImage( ball );
	sprball.SetPosition( 400.f, 300.f );

	// Ask for server address
	sf::IPAddress ServerAddress;
	do
	{
		std::cout << "Type address or name of the server to connect to : ";
		std::cin  >> ServerAddress;
	}
	while (!ServerAddress.IsValid());

	// Create a TCP socket for communicating with server

	

	sf::SocketTCP Client;

	// Connect to the specified server
	if (!Client.Connect(Port, ServerAddress))
		return;
	std::cout << "Connected to server " << ServerAddress << std::endl;

	// Receive a message from the client
	int ToSend = 0;
	int Message = 0;
	//std::size_t Received;
	float ball_x = 400.f, ball_y = 300.f;
	float ball_Xdelta = ballspeed, ball_Ydelta = ballspeed;

	bool key = false;
	bool running = true;
	while( running )
	{

		if( app.GetInput().IsKeyDown( sf::Key::Down ) )
		{
			ToSend = 1;
			spr[1].SetTop( spr[1].GetTop() + paddle_speed );
		}

		if( app.GetInput().IsKeyDown( sf::Key::Up ) )
		{
			ToSend = 2;
			spr[1].SetTop( spr[1].GetTop() - paddle_speed );
		}
		if( !app.GetInput().IsKeyDown( sf::Key::Up ) && !app.GetInput().IsKeyDown( sf::Key::Down ) )
		{
			ToSend = 0;
		}
		if( app.GetInput().IsKeyDown( sf::Key::Escape ) )
		{
			running = false;
		}
		data send;
		send.message = ToSend;
		send.x = 0.0f;
		send.y = 0.0f;
		sf::Packet sendPacket;
		sendPacket << send;
		Client.Send( sendPacket );

		//if (Client.Receive(Message, sizeof(Message), Received) != sf::Socket::Done)
			//return;
		sf::Packet dataPacket;
		if( Client.Receive( dataPacket ) != sf::Socket::Done )
			return;
		data dat;
		if( !(dataPacket >> dat) )
		{
			std::cout << "ERROR" << std::endl;
		}
		ball_x = dat.x;
		ball_y = dat.y;
		Message = dat.message;
		
		// move other players paddle
		if( Message == 1 )
		{
			spr[0].SetTop( spr[0].GetTop() + paddle_speed );
		}
		if( Message == 2 )
		{
			spr[0].SetTop( spr[0].GetTop() - paddle_speed );
		}

		ball_x += ball_Xdelta;
		ball_y += ball_Ydelta;

		sprball.SetPosition( ball_x, ball_y );

		app.Draw( sprball );
		app.Draw( spr[1] );
		app.Draw( spr[0] );

		app.Display();
	}

	// Close the socket when we're done
	Client.Close();
}


////////////////////////////////////////////////////////////
/// Launch a server and wait for incoming connections
///
////////////////////////////////////////////////////////////
void DoServerTCP(unsigned short Port)
{
	sf::RenderWindow app( sf::VideoMode( 800, 600 ),"Server", sf::Style::Resize );
	app.SetBackgroundColor( sf::Color(0,0,0) );


	sf::Image img;
	sf::Image ball;
	img.LoadFromFile( "left_paddle.png" );
	ball.LoadFromFile( "ball.bmp" );

	sf::Sprite spr[2];
	sf::Sprite sprball;

	spr[0].SetImage( img );
	spr[0].SetPosition( 10.f , 10.f );

	spr[1].SetImage( img );
	spr[1].SetPosition( 790.f - spr[1].GetWidth(), 10.f );
	spr[1].FlipX( true );

	sprball.SetImage( ball );
	sprball.SetPosition( 400.f, 300.f );

	// Create a TCP socket for communicating with clients

	

	sf::SocketTCP Server;

	// Listen to a port for incoming connections
	if (!Server.Listen(Port))
		return;
	std::cout << "Server is listening to port " << Port << ", waiting for connections... " << std::endl;

	// Wait for a connection
	sf::IPAddress ClientAddress;
	sf::SocketTCP Client;
	if (Server.Accept(Client, &ClientAddress) != sf::Socket::Done)
		return;
	std::cout << "Client connected : " << ClientAddress << std::endl;

	// Send a message to the client
	int ToSend = 0;
	int Message = 0;
	std::size_t Received;
	float ball_x = 400.f, ball_y = 300.f;
	float ball_Xdelta = ballspeed, ball_Ydelta = ballspeed;

	bool key = false;
	bool running = true;

	while(running)
	{
		if( app.GetInput().IsKeyDown( sf::Key::S ) )
		{
			ToSend = 1;
			spr[0].SetTop( spr[0].GetTop() + paddle_speed );
		}

		if( app.GetInput().IsKeyDown( sf::Key::W ) )
		{
			ToSend = 2;
			spr[0].SetTop( spr[0].GetTop() - paddle_speed );
		}
		if( !app.GetInput().IsKeyDown( sf::Key::W ) && !app.GetInput().IsKeyDown( sf::Key::S ) )
		{
			ToSend = 0;
		}
		if( app.GetInput().IsKeyDown( sf::Key::Escape ) )
		{
			running = false;
		}
		data dat;
		dat.x = ball_x;
		dat.y = ball_y;
		dat.message = ToSend;
		sf::Packet dataPacket;
		dataPacket << dat;
		Client.Send( dataPacket );
		//Client.Send( ToSend, sizeof(ToSend) );

		sf::Packet receivePacket;
		if (Client.Receive(receivePacket) != sf::Socket::Done)
			return;
		data rec;
		receivePacket >> rec;
		 
		Message = rec.message;

		//collision statements here 
		if( sprball.GetTop() < 0 || sprball.GetTop() > 600 )
		{
			ball_Ydelta = -ball_Ydelta;
		}

		if( sprball.GetLeft() + (sprball.GetHeight() / 2) < 20 && (spr[0].GetTop() < sprball.GetTop() +(sprball.GetHeight() / 2) && sprball.GetTop()  + (sprball.GetHeight() / 2) < spr[0].GetTop() + spr[0].GetHeight() ) )
		{
			ball_Xdelta = -ball_Xdelta;
		}
		if( sprball.GetLeft() + (sprball.GetHeight() / 2) > 780 && ( spr[1].GetTop() < sprball.GetTop() + (sprball.GetHeight() / 2) && sprball.GetTop() + (sprball.GetHeight() / 2) < spr[1].GetTop() + spr[1].GetHeight() ) )
		{
			ball_Xdelta = -ball_Xdelta;
		}
		//end collision statements
		
		// move other players paddle
		if( Message == 1)
		{
			spr[1].SetTop( spr[1].GetTop() + paddle_speed );
		}
		if( Message == 2 )
		{
			spr[1].SetTop( spr[1].GetTop() - paddle_speed );
		}

		ball_x += ball_Xdelta;
		ball_y += ball_Ydelta;

		sprball.SetPosition( ball_x, ball_y );

		app.Draw( sprball );
		app.Draw( spr[1] );
		app.Draw( spr[0] );

		app.Display();
	}

	// Close the sockets when we're done
	Client.Close();
	Server.Close();
}
